package com.jplus.plugins.j2cache.proxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jplus.framework.AppConstant;
import com.jplus.framework.aop.proxy.ProxyChain;
import com.jplus.framework.bean.BeanHandle;
import com.jplus.framework.bean.annotation.Component;
import com.jplus.framework.plugin.PluginProxy;
import com.jplus.framework.util.FormatUtil;
import com.jplus.plugins.j2cache.CachePlugin;
import com.jplus.plugins.j2cache.J2Cache;
import com.jplus.plugins.j2cache.annotation.CacheEvict;
import com.jplus.plugins.j2cache.annotation.Cacheable;
import com.jplus.plugins.j2cache.bean.CacheObject;

/**
 * 缓存代理，用于注解实现
 * 
 * @author Yuanqy
 *
 */
@Component
public class J2CachePluginProxy extends PluginProxy {
	private final Logger log = LoggerFactory.getLogger(getClass());

	private String buildKey(Class<?> cls, Method m) {
		String ss = cls.getName() + '.' + m.getName() + FormatUtil.toJSONString(m.getParameterTypes());
		log.debug("[j2cache]:buildKey=" + ss);
		// return SecurityUtil.MD5(ss);
		return ss;
	}

	@Override
	public Object doProxy(ProxyChain pc) throws Throwable {
		Object result = null;
		Method m = pc.getTargetMethod();
		// ================================
		Cacheable cacheA = m.getAnnotation(Cacheable.class);
		String region = null, key = null;
		if (cacheA != null) {
			region = (FormatUtil.isEmpty(cacheA.value()) ? AppConstant.CONFIG.AppName.getValue() : cacheA.value());
			key = cacheA.key().equals("") ? buildKey(pc.getTargetClass(), pc.getTargetMethod()) : cacheA.key();
			CacheObject obj = J2Cache.get(region, key);// 取缓存
			log.debug("[j2cache]:[%s,%s,L%d]=>%s\n", obj.getRegion(), obj.getKey(), obj.getLevel(), obj.getValue());
			if (obj.getValue() != null)
				return obj.getValue();// 返回缓存
		}
		result = pc.doProxyChain();// 执行方法
		if (cacheA != null) {
			J2Cache.set(region, key, result);// 设置新缓存
		}
		// ================================
		CacheEvict cacheE = m.getAnnotation(CacheEvict.class);
		if (cacheE != null) {
			region = (FormatUtil.isEmpty(cacheE.value()) ? AppConstant.CONFIG.AppName.getValue() : cacheE.value());
			key = cacheE.key().equals("") ? buildKey(pc.getTargetClass(), pc.getTargetMethod()) : cacheE.key();
			J2Cache.evict(region, key);// 清空缓存
		}
		return result;
	}

	/**
	 * 获取代理类
	 */
	@Override
	public List<Class<?>> getTargetClassList() {
		List<Class<?>> list = new ArrayList<Class<?>>();
		if (CachePlugin.CACHESTATE) {// 插件开启，才允许代理
			for (Class<?> cls : BeanHandle.beanSet) {
				Method[] ms = cls.getMethods();
				for (Method m : ms) {
					if (m.isAnnotationPresent(Cacheable.class) || m.isAnnotationPresent(CacheEvict.class)) {
						list.add(cls);
						continue;
					}
				}
			}
		}
		return list;
	}
}
